今天 React 好朋友要帶我學習的部分是如何在 Class-based 的元件(component)中透過修改 state 的值來達到更新畫面(UI),而為了幫助自己更快了解,這邊會同時將 React 中事件處理的部分也一併學習,並且搭配一個簡單的測試情境,才可以更好地吸收。
很重要的一個觀念: state 可以用來在 class-based 的元件(component)中,對於資料進行更新。
而在還沒有 React Hook 的時期,這是透過資料來更新畫面(UI)的唯一撰寫方式,然而 React Hook 的出現,使得寫法得以有所變化:這讓我們可以在 Functional 元件(component)中透過修改 state 的值來重新渲染畫面(UI)
這邊我們模擬一個使用情境,並透過這個情境來了解如何在 Class-based 的元件(component)中修改 state 中的資料並觸發 React 重新更新畫面(UI)。
(P.S. 這裡將 Function component 轉換成 Class-based component 的目的是在於了解這兩者之間該如何轉換哦!)
我們先設定一個 Function component 需要的樣子:
const Person = () => {
return (
<div className="person">
<h1>Bill</h1>
<p>Your Age: 29</p>
</div>
);
};
接著,我們將它改寫成 Class-based component,並且也在 state 中新增資料,用來取代目前寫死的值,這邊有幾個小訣竅:
render()
方法實現
constructor
則看個人怎麼決定,而這邊我們將兩種寫法都寫出來比較:// 沒有 constructor 的寫法
class Person extends React.Component {
state = {
person: [
{ name: "Bill", age: "29" },
]
};
render() {
const { person } = this.state;
return (
<div className="person">
<h1>{ person[0].name }</h1>
<p>Your Age: { person[0].age }</p>
</div>
);
};
}
// 有 constructor 的寫法
class Person extends React.Component {
constructor() {
super();
this.state = {
person: [
{ name: "Bill", age: "29" },
]
};
}
render() {
const { person } = this.state;
return (
<div className="person">
<h1>{ person[0].name }</h1>
<p>Your Age: { person[0].age }</p>
</div>
);
};
}
上述的設定,我們已經準備好了一個具有 state 的 Class-based 元件(component),接下來我們還需要先學習一個部分才能更好地觀察元件(component)重新渲染(render),所以我們必須先了解如果在 React 中使用事件(event)。
在 React 官方文件提到:
使用 React element 處理事件跟使用 DOM element 處理事件是十分相似的。
但是依然有一些差異之處:
第一點相信大家都可以了解,是基於在 JS 與 HTML 中的命名規則。
而第二點在文件中也給出了兩個小範例:
<button onclick="activateLasers()">
Activate Lasers
</button>
<button onClick={activateLasers}>
Activate Lasers
</button>
由於事件的值在JSX 中是一個 function,這意謂著如果今天我們改成如下寫法時,會是直接執行這個 function:
<button onClick={activateLasers()}>
Activate Lasers
</button>
了解基本使用事件處理的方式後,接著我們替剛剛改寫成 Class-based 的元件(component)添加一個按鈕,用來改變 state :
class Person extends React.Component {
state = {
person: [
{ name: "Bill", age: "29" },
]
};
switchNameHandler = () => {
console.log('check clicked!');
}
render() {
const { person } = this.state;
return (
<div className="person">
<h1>{ person[0].name }</h1>
<p>Your Age: { person[0].age }</p>
<button onClick={ this.switchNameHandler }>Switch Name</button>
</div>
);
};
}
這邊我們掛上一個 onClick
事件,用來觸發 switchNameHandler
函式,此時應該可以成功取得 check clicked!
的值。
確認 switchNameHandler
函式可以執行後,接著我們要來了解修改 state 的可行與不可行的方式。
首先是不可行的方式,那就是直接修改 state
在文件中正確的使用 State中有提到:
請不要直接修改 State
這並不會導致重新 render component,比如這個範例:
this.state.comment = 'Hello';
而正確修改 state 的方式,就是使用 setState()
,我們將上述的程式碼在修正成符合情境的設定:
相關測試範例,點擊前往。
class Person extends React.Component {
state = {
person: [
{ name: "Bill", age: "29" },
]
};
switchNameHandler = () => {
this.setState({
person: [
{ name: "Alex", age: "25" },
]
})
}
render() {
const { person } = this.state;
return (
<div className="person">
<h1>{ person[0].name }</h1>
<p>Your Age: { person[0].age }</p>
<button onClick={ this.switchNameHandler }>Switch Name</button>
</div>
);
};
}
透過 setState
可以讓我們更新資料的狀態(state),而更新的方式不只一種,上面只是其中一種簡單的方式。
接著讓我們從文件中來看看還有哪幾種更新的方式吧!
在文件中提到了幾個關於使用 setState
的重點,這邊一一條條列出來:
setState
之後就馬上讀取 this.state
的話,因為 setState
並不會總是馬上更新元件,所以如果需要的話則要透過 setState(updater, callback)
的方式處理。 callback
會在完成 component 被重新 render 之後被執行。
setState
中提供完整的 state。
接著我們改寫一下上面的程式碼來呈現吧!
// Person.jsx
import React from "react";
import "./person.css";
export default class Person extends React.Component {
state = {
person: [{ name: "Bill", age: "29" }]
};
// 透過物件的方式進行更新
switchNameHandler = () => {
this.setState({
person: [{ name: "Alex", age: "25" }]
});
};
// 透過 updater 的方式更新
// switchNameHandler = () => {
// this.setState((state) => {
// return {
// person: [{ name: "Alex", age: "25" }]
// };
// });
// };
// 如果需要在更新元件後做某件事情時
// switchNameHandler = () => {
// this.setState(
// (state) => {
// return {
// person: [{ name: "Alex", age: "25" }]
// };
// },
// () => {
// console.log("do something here....");
// }
// );
// };
render() {
const { person } = this.state;
return (
<div className="person">
<h1>{person[0].name}</h1>
<p>Your Age: {person[0].age}</p>
<button onClick={this.switchNameHandler}>Switch Name</button>
</div>
);
}
}
關於在 Class-based 元件中更新 state 的學習就先暫時到這裡囉。
鐵人賽文章與程式碼同步發佈於: